home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 008a / perl40_2.zip / CMD.C < prev    next >
C/C++ Source or Header  |  1991-11-28  |  32KB  |  1,311 lines

  1. /* $RCSfile: cmd.c,v $$Revision: 4.0.1.4 $$Date: 91/11/11 16:29:33 $
  2.  *
  3.  *    Copyright (c) 1991, Larry Wall
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  * $Log:    cmd.c,v $
  9.  * Revision 4.0.1.4  91/11/11  16:29:33  lwall
  10.  * patch19: do {$foo ne "bar";} returned wrong value
  11.  * patch19: some earlier patches weren't propagated to alternate 286 code
  12.  *
  13.  * Revision 4.0.1.3  91/11/05  16:07:43  lwall
  14.  * patch11: random cleanup
  15.  * patch11: "foo\0" eq "foo" was sometimes optimized to true
  16.  * patch11: foreach on null list could spring memory leak
  17.  *
  18.  * Revision 4.0.1.2  91/06/07  10:26:45  lwall
  19.  * patch4: new copyright notice
  20.  * patch4: made some allowances for "semi-standard" C
  21.  *
  22.  * Revision 4.0.1.1  91/04/11  17:36:16  lwall
  23.  * patch1: you may now use "die" and "caller" in a signal handler
  24.  *
  25.  * Revision 4.0  91/03/20  01:04:18  lwall
  26.  * 4.0 baseline.
  27.  *
  28.  */
  29.  
  30.  
  31. #include "EXTERN.h"
  32. #include "perl.h"
  33.  
  34.  
  35. #ifdef I_VARARGS
  36. #  include <varargs.h>
  37. #endif
  38.  
  39.  
  40. static STR str_chop;
  41.  
  42.  
  43. void grow_dlevel();
  44.  
  45.  
  46. /* do longjmps() clobber register variables? */
  47.  
  48.  
  49. #if defined(cray) || defined(STANDARD_C)
  50. #define JMPCLOBBER
  51. #endif
  52.  
  53.  
  54. /* This is the main command loop.  We try to spend as much time in this loop
  55.  * as possible, so lots of optimizations do their activities in here.  This
  56.  * means things get a little sloppy.
  57.  */
  58.  
  59.  
  60. int
  61. cmd_exec(cmdparm,gimme,sp)
  62. CMD *VOLATILE cmdparm;
  63. VOLATILE int gimme;
  64. VOLATILE int sp;
  65. {
  66.     register CMD *cmd = cmdparm;
  67.     SPAT *VOLATILE oldspat;
  68.     VOLATILE int firstsave = savestack->ary_fill;
  69.     VOLATILE int oldsave;
  70.     VOLATILE int aryoptsave;
  71. #ifdef DEBUGGING
  72.     VOLATILE int olddlevel;
  73.     VOLATILE int entdlevel;
  74. #endif
  75.     register STR *retstr = &str_undef;
  76.     register char *tmps;
  77.     register int cmdflags;
  78.     register int match;
  79.     register char *go_to = goto_targ;
  80.     register int newsp = -2;
  81.     register STR **st = stack->ary_array;
  82.     FILE *VOLATILE fp;
  83.     ARRAY *VOLATILE ar;
  84.  
  85.  
  86.     lastsize = 0;
  87. #ifdef DEBUGGING
  88.     entdlevel = dlevel;
  89. #endif
  90. tail_recursion_entry:
  91. #ifdef DEBUGGING
  92.     dlevel = entdlevel;
  93. #endif
  94. #ifdef TAINT
  95.     tainted = 0;    /* Each statement is presumed innocent */
  96. #endif
  97.     if (cmd == Nullcmd) {
  98.     if (gimme == G_ARRAY && newsp > -2)
  99.         return newsp;
  100.     else {
  101.         st[++sp] = retstr;
  102.         return sp;
  103.     }
  104.     }
  105.     cmdflags = cmd->c_flags;    /* hopefully load register */
  106.     if (go_to) {
  107.     if (cmd->c_label && strEQ(go_to,cmd->c_label))
  108.         goto_targ = go_to = Nullch;        /* here at last */
  109.     else {
  110.         switch (cmd->c_type) {
  111.         case C_IF:
  112.         oldspat = curspat;
  113.         oldsave = savestack->ary_fill;
  114. #ifdef DEBUGGING
  115.         olddlevel = dlevel;
  116. #endif
  117.         retstr = &str_yes;
  118.         newsp = -2;
  119.         if (cmd->ucmd.ccmd.cc_true) {
  120. #ifdef DEBUGGING
  121.             if (debug) {
  122.             debname[dlevel] = 't';
  123.             debdelim[dlevel] = '_';
  124.             if (++dlevel >= dlmax)
  125.                 grow_dlevel();
  126.             }
  127. #endif
  128.             newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  129.             st = stack->ary_array;    /* possibly reallocated */
  130.             retstr = st[newsp];
  131.         }
  132.         if (!goto_targ)
  133.             go_to = Nullch;
  134.         curspat = oldspat;
  135.         if (savestack->ary_fill > oldsave)
  136.             restorelist(oldsave);
  137. #ifdef DEBUGGING
  138.         dlevel = olddlevel;
  139. #endif
  140.         cmd = cmd->ucmd.ccmd.cc_alt;
  141.         goto tail_recursion_entry;
  142.         case C_ELSE:
  143.         oldspat = curspat;
  144.         oldsave = savestack->ary_fill;
  145. #ifdef DEBUGGING
  146.         olddlevel = dlevel;
  147. #endif
  148.         retstr = &str_undef;
  149.         newsp = -2;
  150.         if (cmd->ucmd.ccmd.cc_true) {
  151. #ifdef DEBUGGING
  152.             if (debug) {
  153.             debname[dlevel] = 'e';
  154.             debdelim[dlevel] = '_';
  155.             if (++dlevel >= dlmax)
  156.                 grow_dlevel();
  157.             }
  158. #endif
  159.             newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  160.             st = stack->ary_array;    /* possibly reallocated */
  161.             retstr = st[newsp];
  162.         }
  163.         if (!goto_targ)
  164.             go_to = Nullch;
  165.         curspat = oldspat;
  166.         if (savestack->ary_fill > oldsave)
  167.             restorelist(oldsave);
  168. #ifdef DEBUGGING
  169.         dlevel = olddlevel;
  170. #endif
  171.         break;
  172.         case C_BLOCK:
  173.         case C_WHILE:
  174.         if (!(cmdflags & CF_ONCE)) {
  175.             cmdflags |= CF_ONCE;
  176.             if (++loop_ptr >= loop_max) {
  177.             loop_max += 128;
  178.             Renew(loop_stack, loop_max, struct loop);
  179.             }
  180.             loop_stack[loop_ptr].loop_label = cmd->c_label;
  181.             loop_stack[loop_ptr].loop_sp = sp;
  182. #ifdef DEBUGGING
  183.             if (debug & 4) {
  184.             deb("(Pushing label #%d %s)\n",
  185.               loop_ptr, cmd->c_label ? cmd->c_label : "");
  186.             }
  187. #endif
  188.         }
  189. #ifdef JMPCLOBBER
  190.         cmdparm = cmd;
  191. #endif
  192.         match = setjmp(loop_stack[loop_ptr].loop_env);
  193.         if (match) {
  194.             st = stack->ary_array;    /* possibly reallocated */
  195. #ifdef JMPCLOBBER
  196.             cmd = cmdparm;
  197.             cmdflags = cmd->c_flags|CF_ONCE;
  198. #endif
  199.             if (savestack->ary_fill > oldsave)
  200.             restorelist(oldsave);
  201.             switch (match) {
  202.             default:
  203.             fatal("longjmp returned bad value (%d)",match);
  204.             case O_LAST:    /* not done unless go_to found */
  205.             go_to = Nullch;
  206.             if (lastretstr) {
  207.                 retstr = lastretstr;
  208.                 newsp = -2;
  209.             }
  210.             else {
  211.                 newsp = sp + lastsize;
  212.                 retstr = st[newsp];
  213.             }
  214. #ifdef DEBUGGING
  215.             olddlevel = dlevel;
  216. #endif
  217.             curspat = oldspat;
  218.             goto next_cmd;
  219.             case O_NEXT:    /* not done unless go_to found */
  220.             go_to = Nullch;
  221. #ifdef JMPCLOBBER
  222.             newsp = -2;
  223.             retstr = &str_undef;
  224. #endif
  225.             goto next_iter;
  226.             case O_REDO:    /* not done unless go_to found */
  227.             go_to = Nullch;
  228. #ifdef JMPCLOBBER
  229.             newsp = -2;
  230.             retstr = &str_undef;
  231. #endif
  232.             goto doit;
  233.             }
  234.         }
  235.         oldspat = curspat;
  236.         oldsave = savestack->ary_fill;
  237. #ifdef DEBUGGING
  238.         olddlevel = dlevel;
  239. #endif
  240.         if (cmd->ucmd.ccmd.cc_true) {
  241. #ifdef DEBUGGING
  242.             if (debug) {
  243.             debname[dlevel] = 't';
  244.             debdelim[dlevel] = '_';
  245.             if (++dlevel >= dlmax)
  246.                 grow_dlevel();
  247.             }
  248. #endif
  249.             newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  250.             st = stack->ary_array;    /* possibly reallocated */
  251.             if (newsp >= 0)
  252.             retstr = st[newsp];
  253.         }
  254.         if (!goto_targ) {
  255.             go_to = Nullch;
  256.             goto next_iter;
  257.         }
  258. #ifdef DEBUGGING
  259.         dlevel = olddlevel;
  260. #endif
  261.         if (cmd->ucmd.ccmd.cc_alt) {
  262. #ifdef DEBUGGING
  263.             if (debug) {
  264.             debname[dlevel] = 'a';
  265.             debdelim[dlevel] = '_';
  266.             if (++dlevel >= dlmax)
  267.                 grow_dlevel();
  268.             }
  269. #endif
  270.             newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme && (cmdflags & CF_TERM),sp);
  271.             st = stack->ary_array;    /* possibly reallocated */
  272.             if (newsp >= 0)
  273.             retstr = st[newsp];
  274.         }
  275.         if (goto_targ)
  276.             break;
  277.         go_to = Nullch;
  278.         goto finish_while;
  279.         }
  280.         cmd = cmd->c_next;
  281.         if (cmd && cmd->c_head == cmd)
  282.                     /* reached end of while loop */
  283.         return sp;        /* targ isn't in this block */
  284.         if (cmdflags & CF_ONCE) {
  285. #ifdef DEBUGGING
  286.         if (debug & 4) {
  287.             tmps = loop_stack[loop_ptr].loop_label;
  288.             deb("(Popping label #%d %s)\n",loop_ptr,
  289.             tmps ? tmps : "" );
  290.         }
  291. #endif
  292.         loop_ptr--;
  293.         }
  294.         goto tail_recursion_entry;
  295.     }
  296.     }
  297.  
  298.  
  299. until_loop:
  300.  
  301.  
  302.     /* Set line number so run-time errors can be located */
  303.  
  304.  
  305.     curcmd = cmd;
  306.  
  307.  
  308. #ifdef DEBUGGING
  309.     if (debug) {
  310.     if (debug & 2) {
  311.         deb("%s    (%lx)    r%lx    t%lx    a%lx    n%lx    cs%lx\n",
  312.         cmdname[cmd->c_type],cmd,cmd->c_expr,
  313.         cmd->ucmd.ccmd.cc_true,cmd->ucmd.ccmd.cc_alt,cmd->c_next,
  314.         curspat);
  315.     }
  316.     debname[dlevel] = cmdname[cmd->c_type][0];
  317.     debdelim[dlevel] = '!';
  318.     if (++dlevel >= dlmax)
  319.         grow_dlevel();
  320.     }
  321. #endif
  322.  
  323.  
  324.     /* Here is some common optimization */
  325.  
  326.  
  327.     if (cmdflags & CF_COND) {
  328.     switch (cmdflags & CF_OPTIMIZE) {
  329.  
  330.  
  331.     case CFT_FALSE:
  332.         retstr = cmd->c_short;
  333.         newsp = -2;
  334.         match = FALSE;
  335.         if (cmdflags & CF_NESURE)
  336.         goto maybe;
  337.         break;
  338.     case CFT_TRUE:
  339.         retstr = cmd->c_short;
  340.         newsp = -2;
  341.         match = TRUE;
  342.         if (cmdflags & CF_EQSURE)
  343.         goto flipmaybe;
  344.         break;
  345.  
  346.  
  347.     case CFT_REG:
  348.         retstr = STAB_STR(cmd->c_stab);
  349.         newsp = -2;
  350.         match = str_true(retstr);    /* => retstr = retstr, c2 should fix */
  351.         if (cmdflags & (match ? CF_EQSURE : CF_NESURE))
  352.         goto flipmaybe;
  353.         break;
  354.  
  355.  
  356.     case CFT_ANCHOR:    /* /^pat/ optimization */
  357.         if (multiline) {
  358.         if (*cmd->c_short->str_ptr && !(cmdflags & CF_EQSURE))
  359.             goto scanner;    /* just unanchor it */
  360.         else
  361.             break;        /* must evaluate */
  362.         }
  363.         match = 0;
  364.         goto strop;
  365.  
  366.  
  367.     case CFT_STROP:        /* string op optimization */
  368.         match = 1;
  369.       strop:
  370.         retstr = STAB_STR(cmd->c_stab);
  371.         newsp = -2;
  372. #ifndef I286
  373.         if (*cmd->c_short->str_ptr == *str_get(retstr) &&
  374.             (match ? retstr->str_cur == cmd->c_slen - 1 :
  375.                      retstr->str_cur >= cmd->c_slen) &&
  376.             bcmp(cmd->c_short->str_ptr, str_get(retstr),
  377.               cmd->c_slen) == 0 ) {
  378.         if (cmdflags & CF_EQSURE) {
  379.             if (sawampersand && (cmdflags & CF_OPTIMIZE) != CFT_STROP) {
  380.             curspat = Nullspat;
  381.             if (leftstab)
  382.                 str_nset(stab_val(leftstab),"",0);
  383.             if (amperstab)
  384.                 str_sset(stab_val(amperstab),cmd->c_short);
  385.             if (rightstab)
  386.                 str_nset(stab_val(rightstab),
  387.                   retstr->str_ptr + cmd->c_slen,
  388.                   retstr->str_cur - cmd->c_slen);
  389.             }
  390.             if (cmd->c_spat)
  391.             lastspat = cmd->c_spat;
  392.             match = !(cmdflags & CF_FIRSTNEG);
  393.             retstr = match ? &str_yes : &str_no;
  394.             goto flipmaybe;
  395.         }
  396.         }
  397.         else if (cmdflags & CF_NESURE) {
  398.         match = cmdflags & CF_FIRSTNEG;
  399.         retstr = match ? &str_yes : &str_no;
  400.         goto flipmaybe;
  401.         }
  402. #else
  403.         {
  404.         char *zap1, *zap2, zap1c, zap2c;
  405.         int  zaplen;
  406.         int lenok;
  407.  
  408.  
  409.         zap1 = cmd->c_short->str_ptr;
  410.         zap2 = str_get(retstr);
  411.         zap1c = *zap1;
  412.         zap2c = *zap2;
  413.         zaplen = cmd->c_slen;
  414.         if (match)
  415.             lenok = (retstr->str_cur == cmd->c_slen - 1);
  416.         else
  417.             lenok = (retstr->str_cur >= cmd->c_slen);
  418.         if ((zap1c == zap2c) && lenok && (bcmp(zap1, zap2, zaplen) == 0)) {
  419.             if (cmdflags & CF_EQSURE) {
  420.             if (sawampersand &&
  421.               (cmdflags & CF_OPTIMIZE) != CFT_STROP) {
  422.                 curspat = Nullspat;
  423.                 if (leftstab)
  424.                 str_nset(stab_val(leftstab),"",0);
  425.                 if (amperstab)
  426.                 str_sset(stab_val(amperstab),cmd->c_short);
  427.                 if (rightstab)
  428.                 str_nset(stab_val(rightstab),
  429.                      retstr->str_ptr + cmd->c_slen,
  430.                      retstr->str_cur - cmd->c_slen);
  431.             }
  432.             if (cmd->c_spat)
  433.                 lastspat = cmd->c_spat;
  434.              match = !(cmdflags & CF_FIRSTNEG);
  435.             retstr = match ? &str_yes : &str_no;
  436.              goto flipmaybe;
  437.             }
  438.         }
  439.         else if (cmdflags & CF_NESURE) {
  440.             match = cmdflags & CF_FIRSTNEG;
  441.             retstr = match ? &str_yes : &str_no;
  442.             goto flipmaybe;
  443.         }
  444.         }
  445. #endif
  446.         break;            /* must evaluate */
  447.  
  448.  
  449.     case CFT_SCAN:            /* non-anchored search */
  450.       scanner:
  451.         retstr = STAB_STR(cmd->c_stab);
  452.         newsp = -2;
  453.         if (retstr->str_pok & SP_STUDIED)
  454.         if (screamfirst[cmd->c_short->str_rare] >= 0)
  455.             tmps = screaminstr(retstr, cmd->c_short);
  456.         else
  457.             tmps = Nullch;
  458.         else {
  459.         tmps = str_get(retstr);        /* make sure it's pok */
  460. #ifndef lint
  461.         tmps = fbminstr((unsigned char*)tmps,
  462.             (unsigned char*)tmps + retstr->str_cur, cmd->c_short);
  463. #endif
  464.         }
  465.         if (tmps) {
  466.         if (cmdflags & CF_EQSURE) {
  467.             ++cmd->c_short->str_u.str_useful;
  468.             if (sawampersand) {
  469.             curspat = Nullspat;
  470.             if (leftstab)
  471.                 str_nset(stab_val(leftstab),retstr->str_ptr,
  472.                   tmps - retstr->str_ptr);
  473.             if (amperstab)
  474.                 str_nset(stab_val(amperstab),
  475.                   tmps, cmd->c_short->str_cur);
  476.             if (rightstab)
  477.                 str_nset(stab_val(rightstab),
  478.                   tmps + cmd->c_short->str_cur,
  479.                   retstr->str_cur - (tmps - retstr->str_ptr) -
  480.                 cmd->c_short->str_cur);
  481.             }
  482.             lastspat = cmd->c_spat;
  483.             match = !(cmdflags & CF_FIRSTNEG);
  484.             retstr = match ? &str_yes : &str_no;
  485.             goto flipmaybe;
  486.         }
  487.         else
  488.             hint = tmps;
  489.         }
  490.         else {
  491.         if (cmdflags & CF_NESURE) {
  492.             ++cmd->c_short->str_u.str_useful;
  493.             match = cmdflags & CF_FIRSTNEG;
  494.             retstr = match ? &str_yes : &str_no;
  495.             goto flipmaybe;
  496.         }
  497.         }
  498.         if (--cmd->c_short->str_u.str_useful < 0) {
  499.         cmdflags &= ~CF_OPTIMIZE;
  500.         cmdflags |= CFT_EVAL;    /* never try this optimization again */
  501.         cmd->c_flags = (cmdflags & ~CF_ONCE);
  502.         }
  503.         break;            /* must evaluate */
  504.  
  505.  
  506.     case CFT_NUMOP:        /* numeric op optimization */
  507.         retstr = STAB_STR(cmd->c_stab);
  508.         newsp = -2;
  509.         switch (cmd->c_slen) {
  510.         case O_EQ:
  511.         if (dowarn) {
  512.             if ((!retstr->str_nok && !looks_like_number(retstr)))
  513.             warn("Possible use of == on string value");
  514.         }
  515.         match = (str_gnum(retstr) == cmd->c_short->str_u.str_nval);
  516.         break;
  517.         case O_NE:
  518.         match = (str_gnum(retstr) != cmd->c_short->str_u.str_nval);
  519.         break;
  520.         case O_LT:
  521.         match = (str_gnum(retstr) <  cmd->c_short->str_u.str_nval);
  522.         break;
  523.         case O_LE:
  524.         match = (str_gnum(retstr) <= cmd->c_short->str_u.str_nval);
  525.         break;
  526.         case O_GT:
  527.         match = (str_gnum(retstr) >  cmd->c_short->str_u.str_nval);
  528.         break;
  529.         case O_GE:
  530.         match = (str_gnum(retstr) >= cmd->c_short->str_u.str_nval);
  531.         break;
  532.         }
  533.         if (match) {
  534.         if (cmdflags & CF_EQSURE) {
  535.             retstr = &str_yes;
  536.             goto flipmaybe;
  537.         }
  538.         }
  539.         else if (cmdflags & CF_NESURE) {
  540.         retstr = &str_no;
  541.         goto flipmaybe;
  542.         }
  543.         break;            /* must evaluate */
  544.  
  545.  
  546.     case CFT_INDGETS:        /* while (<$foo>) */
  547.         last_in_stab = stabent(str_get(STAB_STR(cmd->c_stab)),TRUE);
  548.         if (!stab_io(last_in_stab))
  549.         stab_io(last_in_stab) = stio_new();
  550.         goto dogets;
  551.     case CFT_GETS:            /* really a while (<file>) */
  552.         last_in_stab = cmd->c_stab;
  553.       dogets:
  554.         fp = stab_io(last_in_stab)->ifp;
  555.         retstr = stab_val(defstab);
  556.         newsp = -2;
  557.       keepgoing:
  558.         if (fp && str_gets(retstr, fp, 0)) {
  559.         if (*retstr->str_ptr == '0' && retstr->str_cur == 1)
  560.             match = FALSE;
  561.         else
  562.             match = TRUE;
  563.         stab_io(last_in_stab)->lines++;
  564.         }
  565.         else if (stab_io(last_in_stab)->flags & IOF_ARGV) {
  566.         if (!fp)
  567.             goto doeval;    /* first time through */
  568.         fp = nextargv(last_in_stab);
  569.         if (fp)
  570.             goto keepgoing;
  571.         (void)do_close(last_in_stab,FALSE);
  572.         stab_io(last_in_stab)->flags |= IOF_START;
  573.         retstr = &str_undef;
  574.         match = FALSE;
  575.         }
  576.         else {
  577.         retstr = &str_undef;
  578.         match = FALSE;
  579.         }
  580.         goto flipmaybe;
  581.     case CFT_EVAL:
  582.         break;
  583.     case CFT_UNFLIP:
  584.         while (tmps_max > tmps_base) {    /* clean up after last eval */
  585.         str_free(tmps_list[tmps_max]);
  586.         tmps_list[tmps_max--] = Nullstr;
  587.         }
  588.         newsp = eval(cmd->c_expr,gimme && (cmdflags & CF_TERM),sp);
  589.         st = stack->ary_array;    /* possibly reallocated */
  590.         retstr = st[newsp];
  591.         match = str_true(retstr);
  592.         if (cmd->c_expr->arg_type == O_FLIP)    /* undid itself? */
  593.         cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
  594.         goto maybe;
  595.     case CFT_CHOP:
  596.         retstr = stab_val(cmd->c_stab);
  597.         newsp = -2;
  598.         match = (retstr->str_cur != 0);
  599.         tmps = str_get(retstr);
  600.         tmps += retstr->str_cur - match;
  601.         str_nset(&str_chop,tmps,match);
  602.         *tmps = '\0';
  603.         retstr->str_nok = 0;
  604.         retstr->str_cur = tmps - retstr->str_ptr;
  605.         STABSET(retstr);
  606.         retstr = &str_chop;
  607.         goto flipmaybe;
  608.     case CFT_ARRAY:
  609.         match = cmd->c_short->str_u.str_useful; /* just to get register */
  610.  
  611.  
  612.         if (match < 0) {        /* first time through here? */
  613.         ar = stab_array(cmd->c_expr[1].arg_ptr.arg_stab);
  614.         aryoptsave = savestack->ary_fill;
  615.         savesptr(&stab_val(cmd->c_stab));
  616.         savelong(&cmd->c_short->str_u.str_useful);
  617.         }
  618.         else {
  619.         ar = stab_xarray(cmd->c_expr[1].arg_ptr.arg_stab);
  620.         if (cmd->c_type != C_WHILE && savestack->ary_fill > firstsave)
  621.             restorelist(firstsave);
  622.         }
  623.  
  624.  
  625.         if (match >= ar->ary_fill) {    /* we're in LAST, probably */
  626.         if (match < 0 &&        /* er, probably not... */
  627.           savestack->ary_fill > aryoptsave)
  628.             restorelist(aryoptsave);
  629.         retstr = &str_undef;
  630.         cmd->c_short->str_u.str_useful = -1;    /* actually redundant */
  631.         match = FALSE;
  632.         }
  633.         else {
  634.         match++;
  635.         if (!(retstr = ar->ary_array[match]))
  636.             retstr = afetch(ar,match,TRUE);
  637.         stab_val(cmd->c_stab) = retstr;
  638.         cmd->c_short->str_u.str_useful = match;
  639.         match = TRUE;
  640.         }
  641.         newsp = -2;
  642.         goto maybe;
  643.     case CFT_D1:
  644.         break;
  645.     case CFT_D0:
  646.         if (DBsingle->str_u.str_nval != 0)
  647.         break;
  648.         if (DBsignal->str_u.str_nval != 0)
  649.         break;
  650.         if (DBtrace->str_u.str_nval != 0)
  651.         break;
  652.         goto next_cmd;
  653.     }
  654.  
  655.  
  656.     /* we have tried to make this normal case as abnormal as possible */
  657.  
  658.  
  659.     doeval:
  660.     if (gimme == G_ARRAY) {
  661.         lastretstr = Nullstr;
  662.         lastspbase = sp;
  663.         lastsize = newsp - sp;
  664.         if (lastsize < 0)
  665.         lastsize = 0;
  666.     }
  667.     else
  668.         lastretstr = retstr;
  669.     while (tmps_max > tmps_base) {    /* clean up after last eval */
  670.         str_free(tmps_list[tmps_max]);
  671.         tmps_list[tmps_max--] = Nullstr;
  672.     }
  673.     newsp = eval(cmd->c_expr,
  674.       gimme && (cmdflags & CF_TERM) && cmd->c_type == C_EXPR &&
  675.         !cmd->ucmd.acmd.ac_expr,
  676.       sp);
  677.     st = stack->ary_array;    /* possibly reallocated */
  678.     retstr = st[newsp];
  679.     if (newsp > sp && retstr)
  680.         match = str_true(retstr);
  681.     else
  682.         match = FALSE;
  683.     goto maybe;
  684.  
  685.  
  686.     /* if flipflop was true, flop it */
  687.  
  688.  
  689.     flipmaybe:
  690.     if (match && cmdflags & CF_FLIP) {
  691.         while (tmps_max > tmps_base) {    /* clean up after last eval */
  692.         str_free(tmps_list[tmps_max]);
  693.         tmps_list[tmps_max--] = Nullstr;
  694.         }
  695.         if (cmd->c_expr->arg_type == O_FLOP) {    /* currently toggled? */
  696.         newsp = eval(cmd->c_expr,G_SCALAR,sp);/*let eval undo it*/
  697.         cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
  698.         }
  699.         else {
  700.         newsp = eval(cmd->c_expr,G_SCALAR,sp);/* let eval do it */
  701.         if (cmd->c_expr->arg_type == O_FLOP)    /* still toggled? */
  702.             cmdflags = copyopt(cmd,cmd->c_expr[4].arg_ptr.arg_cmd);
  703.         }
  704.     }
  705.     else if (cmdflags & CF_FLIP) {
  706.         if (cmd->c_expr->arg_type == O_FLOP) {    /* currently toggled? */
  707.         match = TRUE;                /* force on */
  708.         }
  709.     }
  710.  
  711.  
  712.     /* at this point, match says whether our expression was true */
  713.  
  714.  
  715.     maybe:
  716.     if (cmdflags & CF_INVERT)
  717.         match = !match;
  718.     if (!match)
  719.         goto next_cmd;
  720.     }
  721. #ifdef TAINT
  722.     tainted = 0;    /* modifier doesn't affect regular expression */
  723. #endif
  724.  
  725.  
  726.     /* now to do the actual command, if any */
  727.  
  728.  
  729.     switch (cmd->c_type) {
  730.     case C_NULL:
  731.     fatal("panic: cmd_exec");
  732.     case C_EXPR:            /* evaluated for side effects */
  733.     if (cmd->ucmd.acmd.ac_expr) {    /* more to do? */
  734.         if (gimme == G_ARRAY) {
  735.         lastretstr = Nullstr;
  736.         lastspbase = sp;
  737.         lastsize = newsp - sp;
  738.         if (lastsize < 0)
  739.             lastsize = 0;
  740.         }
  741.         else
  742.         lastretstr = retstr;
  743.         while (tmps_max > tmps_base) {    /* clean up after last eval */
  744.         str_free(tmps_list[tmps_max]);
  745.         tmps_list[tmps_max--] = Nullstr;
  746.         }
  747.         newsp = eval(cmd->ucmd.acmd.ac_expr,gimme && (cmdflags&CF_TERM),sp);
  748.         st = stack->ary_array;    /* possibly reallocated */
  749.         retstr = st[newsp];
  750.     }
  751.     break;
  752.     case C_NSWITCH:
  753.     {
  754.         double value = str_gnum(STAB_STR(cmd->c_stab));
  755.  
  756.  
  757.         match = (int)value;
  758.         if (value < 0.0) {
  759.         if (((double)match) > value)
  760.             --match;        /* was fractional--truncate other way */
  761.         }
  762.     }
  763.     goto doswitch;
  764.     case C_CSWITCH:
  765.     match = *(str_get(STAB_STR(cmd->c_stab))) & 255;
  766.       doswitch:
  767.     match -= cmd->ucmd.scmd.sc_offset;
  768.     if (match < 0)
  769.         match = 0;
  770.     else if (match > cmd->ucmd.scmd.sc_max)
  771.         match = cmd->ucmd.scmd.sc_max;
  772.     cmd = cmd->ucmd.scmd.sc_next[match];
  773.     goto tail_recursion_entry;
  774.     case C_NEXT:
  775.     cmd = cmd->ucmd.ccmd.cc_alt;
  776.     goto tail_recursion_entry;
  777.     case C_ELSIF:
  778.     fatal("panic: ELSIF");
  779.     case C_IF:
  780.     oldspat = curspat;
  781.     oldsave = savestack->ary_fill;
  782. #ifdef DEBUGGING
  783.     olddlevel = dlevel;
  784. #endif
  785.     retstr = &str_yes;
  786.     newsp = -2;
  787.     if (cmd->ucmd.ccmd.cc_true) {
  788. #ifdef DEBUGGING
  789.         if (debug) {
  790.         debname[dlevel] = 't';
  791.         debdelim[dlevel] = '_';
  792.         if (++dlevel >= dlmax)
  793.             grow_dlevel();
  794.         }
  795. #endif
  796.         newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  797.         st = stack->ary_array;    /* possibly reallocated */
  798.         retstr = st[newsp];
  799.     }
  800.     curspat = oldspat;
  801.     if (savestack->ary_fill > oldsave)
  802.         restorelist(oldsave);
  803. #ifdef DEBUGGING
  804.     dlevel = olddlevel;
  805. #endif
  806.     cmd = cmd->ucmd.ccmd.cc_alt;
  807.     goto tail_recursion_entry;
  808.     case C_ELSE:
  809.     oldspat = curspat;
  810.     oldsave = savestack->ary_fill;
  811. #ifdef DEBUGGING
  812.     olddlevel = dlevel;
  813. #endif
  814.     retstr = &str_undef;
  815.     newsp = -2;
  816.     if (cmd->ucmd.ccmd.cc_true) {
  817. #ifdef DEBUGGING
  818.         if (debug) {
  819.         debname[dlevel] = 'e';
  820.         debdelim[dlevel] = '_';
  821.         if (++dlevel >= dlmax)
  822.             grow_dlevel();
  823.         }
  824. #endif
  825.         newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  826.         st = stack->ary_array;    /* possibly reallocated */
  827.         retstr = st[newsp];
  828.     }
  829.     curspat = oldspat;
  830.     if (savestack->ary_fill > oldsave)
  831.         restorelist(oldsave);
  832. #ifdef DEBUGGING
  833.     dlevel = olddlevel;
  834. #endif
  835.     break;
  836.     case C_BLOCK:
  837.     case C_WHILE:
  838.     if (!(cmdflags & CF_ONCE)) {    /* first time through here? */
  839.         cmdflags |= CF_ONCE;
  840.         if (++loop_ptr >= loop_max) {
  841.         loop_max += 128;
  842.         Renew(loop_stack, loop_max, struct loop);
  843.         }
  844.         loop_stack[loop_ptr].loop_label = cmd->c_label;
  845.         loop_stack[loop_ptr].loop_sp = sp;
  846. #ifdef DEBUGGING
  847.         if (debug & 4) {
  848.         deb("(Pushing label #%d %s)\n",
  849.           loop_ptr, cmd->c_label ? cmd->c_label : "");
  850.         }
  851. #endif
  852.     }
  853. #ifdef JMPCLOBBER
  854.     cmdparm = cmd;
  855. #endif
  856.     match = setjmp(loop_stack[loop_ptr].loop_env);
  857.     if (match) {
  858.         st = stack->ary_array;    /* possibly reallocated */
  859. #ifdef JMPCLOBBER
  860.         cmd = cmdparm;
  861.         cmdflags = cmd->c_flags|CF_ONCE;
  862.         go_to = goto_targ;
  863. #endif
  864.         if (savestack->ary_fill > oldsave)
  865.         restorelist(oldsave);
  866.         switch (match) {
  867.         default:
  868.         fatal("longjmp returned bad value (%d)",match);
  869.         case O_LAST:
  870.         if (lastretstr) {
  871.             retstr = lastretstr;
  872.             newsp = -2;
  873.         }
  874.         else {
  875.             newsp = sp + lastsize;
  876.             retstr = st[newsp];
  877.         }
  878.         curspat = oldspat;
  879.         goto next_cmd;
  880.         case O_NEXT:
  881. #ifdef JMPCLOBBER
  882.         newsp = -2;
  883.         retstr = &str_undef;
  884. #endif
  885.         goto next_iter;
  886.         case O_REDO:
  887. #ifdef DEBUGGING
  888.         dlevel = olddlevel;
  889. #endif
  890. #ifdef JMPCLOBBER
  891.         newsp = -2;
  892.         retstr = &str_undef;
  893. #endif
  894.         goto doit;
  895.         }
  896.     }
  897.     oldspat = curspat;
  898.     oldsave = savestack->ary_fill;
  899. #ifdef DEBUGGING
  900.     olddlevel = dlevel;
  901. #endif
  902.     doit:
  903.     if (cmd->ucmd.ccmd.cc_true) {
  904. #ifdef DEBUGGING
  905.         if (debug) {
  906.         debname[dlevel] = 't';
  907.         debdelim[dlevel] = '_';
  908.         if (++dlevel >= dlmax)
  909.             grow_dlevel();
  910.         }
  911. #endif
  912.         newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  913.         st = stack->ary_array;    /* possibly reallocated */
  914.         retstr = st[newsp];
  915.     }
  916.     /* actually, this spot is rarely reached anymore since the above
  917.      * cmd_exec() returns through longjmp().  Hooray for structure.
  918.      */
  919.       next_iter:
  920. #ifdef DEBUGGING
  921.     dlevel = olddlevel;
  922. #endif
  923.     if (cmd->ucmd.ccmd.cc_alt) {
  924. #ifdef DEBUGGING
  925.         if (debug) {
  926.         debname[dlevel] = 'a';
  927.         debdelim[dlevel] = '_';
  928.         if (++dlevel >= dlmax)
  929.             grow_dlevel();
  930.         }
  931. #endif
  932.         newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme && (cmdflags & CF_TERM),sp);
  933.         st = stack->ary_array;    /* possibly reallocated */
  934.         retstr = st[newsp];
  935.     }
  936.       finish_while:
  937.     curspat = oldspat;
  938.     if (savestack->ary_fill > oldsave) {
  939.         if (cmdflags & CF_TERM) {
  940.         for (match = sp + 1; match <= newsp; match++)
  941.             st[match] = str_mortal(st[match]);
  942.         retstr = st[newsp];
  943.         }
  944.         restorelist(oldsave);
  945.     }
  946. #ifdef DEBUGGING
  947.     dlevel = olddlevel - 1;
  948. #endif
  949.     if (cmd->c_type != C_BLOCK)
  950.         goto until_loop;    /* go back and evaluate conditional again */
  951.     }
  952.     if (cmdflags & CF_LOOP) {
  953.     cmdflags |= CF_COND;        /* now test the condition */
  954. #ifdef DEBUGGING
  955.     dlevel = entdlevel;
  956. #endif
  957.     goto until_loop;
  958.     }
  959.   next_cmd:
  960.     if (cmdflags & CF_ONCE) {
  961. #ifdef DEBUGGING
  962.     if (debug & 4) {
  963.         tmps = loop_stack[loop_ptr].loop_label;
  964.         deb("(Popping label #%d %s)\n",loop_ptr, tmps ? tmps : "");
  965.     }
  966. #endif
  967.     loop_ptr--;
  968.     if ((cmdflags & CF_OPTIMIZE) == CFT_ARRAY &&
  969.       savestack->ary_fill > aryoptsave)
  970.         restorelist(aryoptsave);
  971.     }
  972.     cmd = cmd->c_next;
  973.     goto tail_recursion_entry;
  974. }
  975.  
  976.  
  977. #ifdef DEBUGGING
  978. #  ifndef I_VARARGS
  979. /*VARARGS1*/
  980. deb(pat,a1,a2,a3,a4,a5,a6,a7,a8)
  981. char *pat;
  982. {
  983.     register int i;
  984.  
  985.  
  986.     fprintf(stderr,"%-4ld",(long)curcmd->c_line);
  987.     for (i=0; i<dlevel; i++)
  988.     fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
  989.     fprintf(stderr,pat,a1,a2,a3,a4,a5,a6,a7,a8);
  990. }
  991. #  else
  992. /*VARARGS1*/
  993. deb(va_alist)
  994. va_dcl
  995. {
  996.     va_list args;
  997.     char *pat;
  998.     register int i;
  999.  
  1000.  
  1001.     va_start(args);
  1002.     fprintf(stderr,"%-4ld",(long)curcmd->c_line);
  1003.     for (i=0; i<dlevel; i++)
  1004.     fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
  1005.  
  1006.  
  1007.     pat = va_arg(args, char *);
  1008.     (void) vfprintf(stderr,pat,args);
  1009.     va_end( args );
  1010. }
  1011. #  endif
  1012. #endif
  1013.  
  1014.  
  1015. copyopt(cmd,which)
  1016. register CMD *cmd;
  1017. register CMD *which;
  1018. {
  1019.     cmd->c_flags &= CF_ONCE|CF_COND|CF_LOOP;
  1020.     cmd->c_flags |= which->c_flags;
  1021.     cmd->c_short = which->c_short;
  1022.     cmd->c_slen = which->c_slen;
  1023.     cmd->c_stab = which->c_stab;
  1024.     return cmd->c_flags;
  1025. }
  1026.  
  1027.  
  1028. ARRAY *
  1029. saveary(stab)
  1030. STAB *stab;
  1031. {
  1032.     register STR *str;
  1033.  
  1034.  
  1035.     str = Str_new(10,0);
  1036.     str->str_state = SS_SARY;
  1037.     str->str_u.str_stab = stab;
  1038.     if (str->str_ptr) {
  1039.     Safefree(str->str_ptr);
  1040.     str->str_ptr = Nullch;
  1041.     str->str_len = 0;
  1042.     }
  1043.     str->str_ptr = (char*)stab_array(stab);
  1044.     (void)apush(savestack,str); /* save array ptr */
  1045.     stab_xarray(stab) = Null(ARRAY*);
  1046.     return stab_xarray(aadd(stab));
  1047. }
  1048.  
  1049.  
  1050. HASH *
  1051. savehash(stab)
  1052. STAB *stab;
  1053. {
  1054.     register STR *str;
  1055.  
  1056.  
  1057.     str = Str_new(11,0);
  1058.     str->str_state = SS_SHASH;
  1059.     str->str_u.str_stab = stab;
  1060.     if (str->str_ptr) {
  1061.     Safefree(str->str_ptr);
  1062.     str->str_ptr = Nullch;
  1063.     str->str_len = 0;
  1064.     }
  1065.     str->str_ptr = (char*)stab_hash(stab);
  1066.     (void)apush(savestack,str); /* save hash ptr */
  1067.     stab_xhash(stab) = Null(HASH*);
  1068.     return stab_xhash(hadd(stab));
  1069. }
  1070.  
  1071.  
  1072. void
  1073. saveitem(item)
  1074. register STR *item;
  1075. {
  1076.     register STR *str;
  1077.  
  1078.  
  1079.     (void)apush(savestack,item);        /* remember the pointer */
  1080.     str = Str_new(12,0);
  1081.     str_sset(str,item);
  1082.     (void)apush(savestack,str);            /* remember the value */
  1083. }
  1084.  
  1085.  
  1086. void
  1087. saveint(intp)
  1088. int *intp;
  1089. {
  1090.     register STR *str;
  1091.  
  1092.  
  1093.     str = Str_new(13,0);
  1094.     str->str_state = SS_SINT;
  1095.     str->str_u.str_useful = (long)*intp;    /* remember value */
  1096.     if (str->str_ptr) {
  1097.     Safefree(str->str_ptr);
  1098.     str->str_len = 0;
  1099.     }
  1100.     str->str_ptr = (char*)intp;        /* remember pointer */
  1101.     (void)apush(savestack,str);
  1102. }
  1103.  
  1104.  
  1105. void
  1106. savelong(longp)
  1107. long *longp;
  1108. {
  1109.     register STR *str;
  1110.  
  1111.  
  1112.     str = Str_new(14,0);
  1113.     str->str_state = SS_SLONG;
  1114.     str->str_u.str_useful = *longp;        /* remember value */
  1115.     if (str->str_ptr) {
  1116.     Safefree(str->str_ptr);
  1117.     str->str_len = 0;
  1118.     }
  1119.     str->str_ptr = (char*)longp;        /* remember pointer */
  1120.     (void)apush(savestack,str);
  1121. }
  1122.  
  1123.  
  1124. void
  1125. savesptr(sptr)
  1126. STR **sptr;
  1127. {
  1128.     register STR *str;
  1129.  
  1130.  
  1131.     str = Str_new(15,0);
  1132.     str->str_state = SS_SSTRP;
  1133.     str->str_magic = *sptr;        /* remember value */
  1134.     if (str->str_ptr) {
  1135.     Safefree(str->str_ptr);
  1136.     str->str_len = 0;
  1137.     }
  1138.     str->str_ptr = (char*)sptr;        /* remember pointer */
  1139.     (void)apush(savestack,str);
  1140. }
  1141.  
  1142.  
  1143. void
  1144. savenostab(stab)
  1145. STAB *stab;
  1146. {
  1147.     register STR *str;
  1148.  
  1149.  
  1150.     str = Str_new(16,0);
  1151.     str->str_state = SS_SNSTAB;
  1152.     str->str_magic = (STR*)stab;    /* remember which stab to free */
  1153.     (void)apush(savestack,str);
  1154. }
  1155.  
  1156.  
  1157. void
  1158. savehptr(hptr)
  1159. HASH **hptr;
  1160. {
  1161.     register STR *str;
  1162.  
  1163.  
  1164.     str = Str_new(17,0);
  1165.     str->str_state = SS_SHPTR;
  1166.     str->str_u.str_hash = *hptr;    /* remember value */
  1167.     if (str->str_ptr) {
  1168.     Safefree(str->str_ptr);
  1169.     str->str_len = 0;
  1170.     }
  1171.     str->str_ptr = (char*)hptr;        /* remember pointer */
  1172.     (void)apush(savestack,str);
  1173. }
  1174.  
  1175.  
  1176. void
  1177. saveaptr(aptr)
  1178. ARRAY **aptr;
  1179. {
  1180.     register STR *str;
  1181.  
  1182.  
  1183.     str = Str_new(17,0);
  1184.     str->str_state = SS_SAPTR;
  1185.     str->str_u.str_array = *aptr;    /* remember value */
  1186.     if (str->str_ptr) {
  1187.     Safefree(str->str_ptr);
  1188.     str->str_len = 0;
  1189.     }
  1190.     str->str_ptr = (char*)aptr;        /* remember pointer */
  1191.     (void)apush(savestack,str);
  1192. }
  1193.  
  1194.  
  1195. void
  1196. savelist(sarg,maxsarg)
  1197. register STR **sarg;
  1198. int maxsarg;
  1199. {
  1200.     register STR *str;
  1201.     register int i;
  1202.  
  1203.  
  1204.     for (i = 1; i <= maxsarg; i++) {
  1205.     (void)apush(savestack,sarg[i]);        /* remember the pointer */
  1206.     str = Str_new(18,0);
  1207.     str_sset(str,sarg[i]);
  1208.     (void)apush(savestack,str);            /* remember the value */
  1209.     sarg[i]->str_u.str_useful = -1;
  1210.     }
  1211. }
  1212.  
  1213.  
  1214. void
  1215. restorelist(base)
  1216. int base;
  1217. {
  1218.     register STR *str;
  1219.     register STR *value;
  1220.     register STAB *stab;
  1221.  
  1222.  
  1223.     if (base < -1)
  1224.     fatal("panic: corrupt saved stack index");
  1225.     while (savestack->ary_fill > base) {
  1226.     value = apop(savestack);
  1227.     switch (value->str_state) {
  1228.     case SS_NORM:                /* normal string */
  1229.     case SS_INCR:
  1230.         str = apop(savestack);
  1231.         str_replace(str,value);
  1232.         STABSET(str);
  1233.         break;
  1234.     case SS_SARY:                /* array reference */
  1235.         stab = value->str_u.str_stab;
  1236.         afree(stab_xarray(stab));
  1237.         stab_xarray(stab) = (ARRAY*)value->str_ptr;
  1238.         value->str_ptr = Nullch;
  1239.         str_free(value);
  1240.         break;
  1241.     case SS_SHASH:                /* hash reference */
  1242.         stab = value->str_u.str_stab;
  1243.         (void)hfree(stab_xhash(stab), FALSE);
  1244.         stab_xhash(stab) = (HASH*)value->str_ptr;
  1245.         value->str_ptr = Nullch;
  1246.         str_free(value);
  1247.         break;
  1248.     case SS_SINT:                /* int reference */
  1249.         *((int*)value->str_ptr) = (int)value->str_u.str_useful;
  1250.         value->str_ptr = Nullch;
  1251.         str_free(value);
  1252.         break;
  1253.     case SS_SLONG:                /* long reference */
  1254.         *((long*)value->str_ptr) = value->str_u.str_useful;
  1255.         value->str_ptr = Nullch;
  1256.         str_free(value);
  1257.         break;
  1258.     case SS_SSTRP:                /* STR* reference */
  1259.         *((STR**)value->str_ptr) = value->str_magic;
  1260.         value->str_magic = Nullstr;
  1261.         value->str_ptr = Nullch;
  1262.         str_free(value);
  1263.         break;
  1264.     case SS_SHPTR:                /* HASH* reference */
  1265.         *((HASH**)value->str_ptr) = value->str_u.str_hash;
  1266.         value->str_ptr = Nullch;
  1267.         str_free(value);
  1268.         break;
  1269.     case SS_SAPTR:                /* ARRAY* reference */
  1270.         *((ARRAY**)value->str_ptr) = value->str_u.str_array;
  1271.         value->str_ptr = Nullch;
  1272.         str_free(value);
  1273.         break;
  1274.     case SS_SNSTAB:
  1275.         stab = (STAB*)value->str_magic;
  1276.         value->str_magic = Nullstr;
  1277.         (void)stab_clear(stab);
  1278.         str_free(value);
  1279.         break;
  1280.     case SS_SCSV:                /* callsave structure */
  1281.         {
  1282.         CSV *csv = (CSV*) value->str_ptr;
  1283.  
  1284.  
  1285.         curcmd = csv->curcmd;
  1286.         curcsv = csv->curcsv;
  1287.         csv->sub->depth = csv->depth;
  1288.         if (csv->hasargs) {        /* put back old @_ */
  1289.             afree(csv->argarray);
  1290.             stab_xarray(defstab) = csv->savearray;
  1291.         }
  1292.         str_free(value);
  1293.         }
  1294.         break;
  1295.     default:
  1296.         fatal("panic: restorelist inconsistency");
  1297.     }
  1298.     }
  1299. }
  1300.  
  1301.  
  1302. #ifdef DEBUGGING
  1303. void
  1304. grow_dlevel()
  1305. {
  1306.     dlmax += 128;
  1307.     Renew(debname, dlmax, char);
  1308.     Renew(debdelim, dlmax, char);
  1309. }
  1310. #endif
  1311.